﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Castle.ActiveRecord;
using Castle.Components.Validator;

namespace Matriculex.Dominio
{
    public abstract class IdentityFieldProvider<T> : ActiveRecordValidationBase<T>
        where T : IdentityFieldProvider<T>
    {
        [PrimaryKey]
        public virtual int Id { get; private set; }

        public override bool Equals(object obj)
        {
            T other = obj as T;
            if (other == null)
                return false;

            // handle the case of comparing two NEW objects
            bool otherIsTransient = Equals(other.Id, default(int));
            bool thisIsTransient = Equals(Id, default(int));
            if (otherIsTransient && thisIsTransient)
                return ReferenceEquals(other, this);

            return other.Id.Equals(Id);
        }

        private int? _oldHashCode;

        public override int GetHashCode()
        {
            // Once we have a hash code we'll never change it
            if (_oldHashCode.HasValue)
                return _oldHashCode.Value;

            bool thisIsTransient = Equals(Id, default(int));

            // When this instance is transient, we use the base GetHashCode()
            // and remember it, so an instance can NEVER change its hash code.
            if (thisIsTransient)
            {
                _oldHashCode = base.GetHashCode();
                return _oldHashCode.Value;
            }
            return Id.GetHashCode();
        }

        public static bool operator ==(IdentityFieldProvider<T> x, IdentityFieldProvider<T> y)
        {
            return Equals(x, y);
        }

        public static bool operator !=(IdentityFieldProvider<T> x, IdentityFieldProvider<T> y)
        {
            return !(x == y);
        }

        public bool IsTransient()
        {
            return Equals(Id, default(int));
        }


       
        protected override void OnNotValid()
        {
            try
            {
                base.OnNotValid();
            }
            catch (Castle.Components.Validator.ValidationException)
            {
                throw new ValidationException(this.ValidationErrorMessages[0]);
            }
        }


    }
}
